﻿// -----------------------------------------------------------------------
// <copyright file="commServer.cs" company="Microsoft">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace TCPIPServer
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Threading;
    using System.Net.Sockets;
    using System.Text;
    using System.Collections;

    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    public class commServer
    {

        public static Hashtable clientsList = new Hashtable();

        public delegate void delegateTransmissionReceived(string text);
        public event delegateTransmissionReceived TransmissionReceived;

        public delegate void delegateNewClientConnected(string text);
        public event delegateNewClientConnected NewClientConnected;

        private int _port = 8888;
        private Thread _ctThread = null;
        private handleClient _client = null;

        TcpListener _serverSocket = null;
        TcpClient _clientSocket = null;

        private bool _isListening = false;

        bool _abort = false;

        public commServer()
        {
        }

        public void StartListening(int Port)
        {
            this._abort = false;
            this._port = Port;
            this._isListening = true;
            this._ctThread = new Thread(listening);
            this._ctThread.Start();
        }

        public void StopListening()
        {
            this._isListening = false;
            this._abort = true;
            if (this._client != null) this._client.stopClient();
            this._serverSocket.Stop();
            this._ctThread.Abort();
            //this._clientSocket.Close();
        }

        public bool IsListening
        {
            get { return this._isListening; }
        }

        private void listening()
        {
            this._serverSocket = new TcpListener(this._port);
            this._clientSocket = default(TcpClient);
            //int counter = 0;

            this._serverSocket.Start();
            Console.WriteLine("TCP/IP Server Started listening on port " + Convert.ToString(this._port));
            //counter = 0;
            while ((this._abort == false))
            {
                try
                {
                    //counter += 1;
                    this._clientSocket = this._serverSocket.AcceptTcpClient();

                    byte[] bytesFrom = new byte[10025];
                    string dataFromClient = null;

                    if (this._clientSocket.Connected)
                    {
                        NetworkStream networkStream = this._clientSocket.GetStream();
                        //networkStream.Read(bytesFrom, 0, this._clientSocket.ReceiveBufferSize);
                        int readBytes = networkStream.Read(bytesFrom, 0, 1024);
                        dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
                        //dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
                        dataFromClient = dataFromClient.Substring(0, readBytes - 1);

                        clientsList.Add(dataFromClient, this._clientSocket);

                        if (this.NewClientConnected != null)
                        {
                            this.NewClientConnected(dataFromClient);
                        }
                        //broadcast(dataFromClient + " Joined ");
                        //Console.WriteLine(dataFromClient + " Joined");

                    }

                    this._client = new handleClient();
                    this._client.TransmissionRFeceived += this.ReceivedDataFromClient;

                    this._client.startClient(this._clientSocket, dataFromClient, clientsList);
                }
                catch (Exception e)
                {
                }
            }

            this._clientSocket.Close();
            this._serverSocket.Stop();
            Console.WriteLine("exit");
            Console.ReadLine();

        }

        public static void broadcast(string msg)
        {
            object itemKeyForDeletion = null;

            foreach (DictionaryEntry Item in clientsList)
            {
                TcpClient broadcastSocket;
                broadcastSocket = (TcpClient)Item.Value;
                if (broadcastSocket.Connected == true)
                {
                    NetworkStream broadcastStream = broadcastSocket.GetStream();
                    Byte[] broadcastBytes = null;

                    broadcastBytes = Encoding.ASCII.GetBytes(msg);

                    broadcastStream.Write(broadcastBytes, 0, broadcastBytes.Length);
                    broadcastStream.Flush();
                } else
                {
                    itemKeyForDeletion = Item.Key;
                }
            }
            if (itemKeyForDeletion != null)
            {
                clientsList.Remove(itemKeyForDeletion);
            }
        }  //end broadcast function


        private void ReceivedDataFromClient(string dataFromClient)
        {
            if (this.TransmissionReceived != null)
            {
                this.TransmissionReceived(dataFromClient);
            }
        }
    }

    public class handleClient
    {
        TcpClient clientSocket;
        string clNo;
        Hashtable clientsList;
        Thread ctThread = null;
        bool _abort = false;

        public delegate void delegateTransmissionReceived(string text);
        public event delegateTransmissionReceived TransmissionRFeceived;


        public void startClient(TcpClient inClientSocket, string clineNo, Hashtable cList)
        {
            this._abort = false;
            this.clientSocket = inClientSocket;
            this.clNo = clineNo;
            this.clientsList = cList;
            ctThread = new Thread(doTransmission);
            ctThread.Start();
        }

        public void stopClient()
        {
            this._abort = true;
            this.ctThread.Abort();
            this.clientSocket.Close();
        }

        private void doTransmission()
        {
            int requestCount = 0;
            byte[] bytesFrom = new byte[10025];
            string dataFromClient = null;
            Byte[] sendBytes = null;
            string serverResponse = null;
            string rCount = null;
            requestCount = 0;

            while (this._abort == false)
            {
                try
                {
                    requestCount = requestCount + 1;
                    if (clientSocket.Connected)
                    {
                        NetworkStream networkStream = clientSocket.GetStream();
                        //networkStream.Read(bytesFrom, 0, (int)clientSocket.ReceiveBufferSize);
                        int readBytes = networkStream.Read(bytesFrom, 0, 1024);
                        dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
                        //dataFromClient = dataFromClient.Substring(0, dataFromClient.IndexOf("$"));
                        if (readBytes > 0)
                        {
                            dataFromClient = dataFromClient.Substring(0, readBytes - 1);
                            Console.WriteLine("From client - " + clNo + " : " + dataFromClient);
                        } else
                        {
                            dataFromClient = "";
                        }
                    }
                    else 
                    {
                        return;
                    }

                    if (this.TransmissionRFeceived != null)
                    {
                        this.TransmissionRFeceived(dataFromClient);
                    }

                    rCount = Convert.ToString(requestCount);

                    commServer.broadcast(dataFromClient);
                }

                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }

            }//end while

        }//end doChat

    } //end class handleClinet

}
